/**
 * 在编译之前，每个代码 (.cpp) 文件都会经历一个预处理阶段。
 * 在此阶段，称为预处理器的程序对代码文件的文本进行各种更改。
 * 预处理器实际上不会以任何方式修改原始代码文件——相反，预处理器所做的所有更改要么临时发生在内存中，要么使用临时文件。
 * 
 * 从历史上看，预处理器是与编译器分开的程序，但在现代编译器中，预处理器可以直接构建到编译器本身中。
 * 
 * 请注意，预处理器不理解 C++ 语法——相反，指令有自己的语法（在某些情况下类似于 C++ 语法，而在其他情况下则不太相似）。
 * 
 * 当您#include文件时，预处理器会将 #include 指令替换为所包含文件的内容。然后对包含的内容进行预处理（这可能会导致递归地预处理额外的#include），然后对文件的其余部分进行预处理。
 * 
 * 宏定义
 * #define指令可用于创建宏。在 C++ 中，宏是定义如何将输入文本转换为替换输出文本的规则。
 * 宏有两种基本类型：类对象宏和类函数宏。
 * #define identifier
 * #define identifier substitution_text
 * 
 * 宏的标识符使用与普通标识符相同的命名规则：可以使用字母、数字和下划线，不能以数字开头，也不应该以下划线开头。按照惯例，宏名称通常全部大写，并用下划线分隔。
 * 
 * 条件编译
 * 条件编译预处理器指令允许您指定在什么条件下某些内容将或不会编译。有很多不同的条件编译指令，但我们只介绍迄今为止最常用的三个：#ifdef、#ifndef和#endif。
 * #ifdef预处理器指令允许预处理器检查标识符是否先前已被#define过。如果是这样，则编译#ifdef和匹配的#endif之间的代码。如果不是，则忽略该代码。
 * 
 */

#include <iostream>

int main()
{
    std::cout << "Hello, world!\n";
    return 0;
}




#include <iostream>

#define MY_NAME "Alex"

int main2()
{
    std::cout << "My name is: " << MY_NAME << '\n';
    // std::cout << "My name is: " << "Alex" << '\n'; // 被替换成

    return 0;
}




#include <iostream>

#define PRINT_JOE

int main3()
{
#ifdef PRINT_JOE
    std::cout << "Joe\n"; // will be compiled since PRINT_JOE is defined
#endif

#ifdef PRINT_BOB
    std::cout << "Bob\n"; // will be excluded since PRINT_BOB is not defined
#endif

#ifndef PRINT_BOB
    std::cout << "no bob\n";
#endif

    return 0;
}